package com.power.sifa.util.service.impl;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.power.sifa.util.service.SmsService;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import lombok.extern.slf4j.Slf4j;

/**
 * 联通的经分助手短信
 * https://flaginfo-cloud.yuque.com/staff-rozzgq/zsss51/plrl67?singleDoc#
 * sms:
	  enable: false
	  type: infocloud
	  apikey: 400db2bea2ffcbbb0d2e017a7d95d10c
	  secretkey: a3832e0faf59b9250217e08018b214e71bfe161f5507ac7b6a3f6476f7041fcf
	  tpl_fileaccept: 919685319979724800
 * @author wangn
 */
@Slf4j
@Service
@ConditionalOnProperty(prefix = "sms", name = "type", havingValue="infocloud")
public class InfoCloudSmsServiceImpl implements SmsService{
	private static final String URL_SEND = "https://opassapi.infocloud.cc/message/send";

	@Value("${sms.enable:#{false}}")
    public Boolean enable = false;
	
	@Value("${sms.apikey:#{'400db2bea2ffcbbb0d2e017a7d95d10c'}}")
    public String api_key = "400db2bea2ffcbbb0d2e017a7d95d10c";
	
	@Value("${sms.secretkey:#{'a3832e0faf59b9250217e08018b214e71bfe161f5507ac7b6a3f6476f7041fcf'}}")
    public String secret_key = "a3832e0faf59b9250217e08018b214e71bfe161f5507ac7b6a3f6476f7041fcf";
    
    /**
     * 签名加密工具类
     */
    private HmacUtils hmacUtil;
    
    /**
     * 签名加密算法
     */
    private HmacAlgorithms algorithem=HmacAlgorithms.HMAC_SHA_224;

	@Override
	public String sendTemplate(String tpl_code, List<String> params, String... mobile) {
		String msgid=null;
		if(!enable) {
			log.info("短信开关未开启 sms.enable: false");
			return msgid;
		}
		
		Assert.notNull(tpl_code, "模板编码不得为空");
		String mobileStr=Arrays.stream(mobile).collect(Collectors.toSet()).stream().collect(Collectors.joining(","));
		String paramsJson=JSON.toJSONString(params);
		
		Map<String, String> headers = getHeaders();
        Map<String, String> bodyParams = new HashMap<>(4);
        bodyParams.put("templateCode", tpl_code);
        bodyParams.put("phones", mobileStr);
        bodyParams.put("templateParam", paramsJson);
        
        SortedMap<String, String> sortedMap = new TreeMap<>(bodyParams);
        headers.forEach((k, v) -> sortedMap.put(k, v));
        headers.put("x-sign", getSignature(sortedMap));
        
        HttpResponse response = null;
        response = HttpRequest.post(URL_SEND)
        		.headerMap(headers, false)
        		.body(JSON.toJSONString(bodyParams))
        		.timeout(10000)
        		.execute();
        String re=response.body();
        log.info("发送短信返回 {}", re);
        
        JSONObject reJson=JSON.parseObject(re);
        String code=reJson.getString("code");
        if(code!=null && code.equals("200")) {
        	JSONObject data=reJson.getJSONObject("data");
        	if(data!=null) {
        		msgid=data.getString("msgId");
        	}
        }else {
            log.error("发送短信失败");
        }
		return msgid;
	}

	/**
	 * 生成请求header
	 * @return header map
	 */
	private Map<String, String> getHeaders() {
		Map<String, String> headers = new HashMap<>();
		String nonce = RandomUtil.randomString(10);
		
        headers.put("x-api-key", api_key);
        headers.put("x-sign-method", algorithem.getName());
        headers.put("x-nonce", nonce);
        headers.put("x-timestamp", String.valueOf(System.currentTimeMillis()));
        return headers;
	}

	/**
	 * 根据请求body，生成签名串
	 * @param sortedMap
	 * @return 签名串
	 */
	private String getSignature(SortedMap<String, String> sortedMap) {
		String sign=null;
		StringBuffer plainText = new StringBuffer();
        for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
            plainText.append(entry.getKey() + "=" + entry.getValue());
            plainText.append("&");
        }
        
        if(StringUtils.hasLength(plainText)) {
            plainText.deleteCharAt(plainText.length() - 1);
        }
        
        if(hmacUtil==null) {
        	hmacUtil=new HmacUtils(algorithem, secret_key);
        }
        
        sign=hmacUtil.hmacHex(plainText.toString());
		return sign;
	}

}
